<script setup>
import { nextTick, onMounted, reactive, ref } from 'vue'

const props = defineProps({
    url: {
        default: ''
    },
    memoryTime: {
        default: ''
    },
    autoplay: {
        default: true,
        type: Boolean
    }
})

const emit = defineEmits(['updateTime'])

const audioDom = ref()
const state = reactive({
    loadCount: 0,
    loading: true,
    duration: 0,
    currentTime: 0,
    playing: false,
    progress: 0,
    isDragging: false,
    src: 'https://mp3cdn.testgts.com/static/toefl/tpo/changVolume.mp3',
    showRate: false,
    rate: 1
})

if (props.url) {
    state.src = props.url
}

onMounted(() => {
    nextTick(() => {
        audioDom.value.load()

        audioDom.value.addEventListener('canplay', () => {
            state.duration = audioDom.value.duration
        })
        audioDom.value.addEventListener('canplaythrough', () => {
            state.loading = false
            console.log('可以播放')
        })
        audioDom.value.addEventListener('error', () => {
            console.log('加载失败')
        })
        audioDom.value.addEventListener('loadedmetadata', () => {
            console.log('加载中')
        })
        audioDom.value.addEventListener('loadeddata', () => {
            console.log('加载完成')
            // 记忆播放
            if (props.memoryTime) {
                audioDom.value.currentTime = Number(props.memoryTime)
            }
        })
        audioDom.value.addEventListener('play', () => {
            state.playing = true
        })
        audioDom.value.addEventListener('pause', () => {
            state.playing = false
        })
        audioDom.value.addEventListener('timeupdate', () => {
            if (!audioDom.value) {
                return
            }
            state.currentTime = audioDom.value.currentTime
            state.progress = (audioDom.value.currentTime / audioDom.value.duration) * 100
            emit('updateTime', audioDom.value.currentTime)
        })
    })
})

// 时间格式
function timeFormat(time) {
    let s = Math.floor(time % 60)
    let m = Math.floor(time / 60)
    if (s < 10) s = '0' + s
    if (m < 10) m = '0' + m
    return m + ':' + s
}

// 暂停或播放
function musicPlay() {
    if (state.src === '') {
        return
    }
    if (!state.playing) {
        audioDom.value.play().catch(() => {
            console.log('这个播放器好像不支持这个类型的文件')
        })
    } else {
        audioDom.value.pause()
    }
}

// 滑块拖动
const onChange = (value) => {
    audioDom.value.currentTime = (value / 100) * audioDom.value.duration
}

// 修改播放速率
const changePlaybackRate = (rate) => {
    state.showRate = false
    audioDom.value.playbackRate = rate
    state.rate = rate
}

// 暂停播放
const pause = () => {
    audioDom.value.pause()
}

// 播放音频
const play = () => {
    if (state.loading) {
        setTimeout(() => {
            state.loadCount++
            if (state.loadCount >= 5) {
                state.loading = false
            }
            play()
        }, 1000)
    } else {
        audioDom.value.play()
    }
}

function getCurrentTime() {
    return state.currentTime
}

function setCurrentTime(time) {
    audioDom.value.currentTime = time
}

defineExpose({
    pause,
    play,
    getCurrentTime,
    setCurrentTime
})
</script>

<template>
    <div class="player-com">
        <div class="player-blank">
            <div class="time">{{ timeFormat(state.currentTime) }}</div>
            <div class="process">
                <van-slider
                    v-model="state.progress"
                    bar-height="4px"
                    active-color="#FD453D"
                    inactive-color="#D4D4D8"
                    @change="onChange">
                    <template #button>
                        <div class="custom-button"></div>
                    </template>
                </van-slider>
            </div>
            <div class="totalTime">
                {{ timeFormat(state.duration) }}
            </div>
        </div>
        <div class="control-blank">
            <!--   选择播放速度     -->
            <div v-show="state.showRate">
                <div class="rate-list">
                    <ul>
                        <li
                            @click="changePlaybackRate(0.75)"
                            :class="{ active: state.rate === 0.75 }">
                            0.75x
                        </li>
                        <li
                            @click="changePlaybackRate(1.0)"
                            :class="{ active: state.rate === 1.0 }">
                            1.0x
                        </li>
                        <li
                            @click="changePlaybackRate(1.25)"
                            :class="{ active: state.rate === 1.25 }">
                            1.25x
                        </li>
                        <li
                            @click="changePlaybackRate(1.5)"
                            :class="{ active: state.rate === 1.5 }">
                            1.5x
                        </li>
                        <li
                            @click="changePlaybackRate(2.0)"
                            :class="{ active: state.rate === 2.0 }">
                            2.0x
                        </li>
                    </ul>
                </div>
                <div class="spike"></div>
            </div>
            <div class="rate-blank" @click="state.showRate = !state.showRate">
                <span class="text">倍速</span>
                <span class="rate-val">{{ state.rate }}x</span>
            </div>
            <div
                v-show="!state.loading"
                class="play-btn"
                :class="{ 'pause-btn': state.playing }"
                @click="musicPlay"></div>
            <div v-show="state.loading" class="load-btn">
                <van-loading color="white" type="spinner" size="24px" />
            </div>
            <div class="rate-blank" style="opacity: 0"></div>
        </div>
        <audio
            ref="audioDom"
            id="audioPlay"
            style="display: none"
            controls
            preload="auto"
            :autoplay="props.autoplay"
            :src="state.src"></audio>
    </div>
</template>

<style scoped lang="scss">
.player-com {
    padding: 0 15px;
    background: #ffffff;
}
.player-blank {
    display: flex;
    align-items: center;
    justify-content: space-evenly;
    .time {
        width: 2.8rem;
        text-align: left;
        color: #999999;
        font-size: 0.75rem;
    }
    .process {
        flex: 1;
    }
    .totalTime {
        font-size: 0.75rem;
        color: #999999;
        width: 2.8rem;
        text-align: right;
    }
}
.control-blank {
    position: relative;
    height: 50px;
    line-height: 50px;
    text-align: center;
    display: flex;
    align-items: center;
    .rate-list {
        position: absolute;
        left: 0;
        bottom: 50px;
        width: 100px;
        background: #ffffff;
        color: #333333;
        font-size: 14px;
        z-index: 1;
        border-left: 1px solid #ececec;
        border-right: 1px solid #ececec;
        box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.2);
        ul {
            list-style: none;
            li {
                border-bottom: 1px solid #ececec;
                height: 30px;
                line-height: 30px;
                text-align: center;
            }
            li:last-child {
                border-bottom: none;
            }
            .active {
                color: #fd453d;
            }
        }
    }
    .spike {
        position: absolute;
        left: 24px;
        bottom: 45px;
        width: 10px;
        height: 10px;
        background: #ffffff;
        border-left: 1px solid #ffffff;
        border-right: 1px solid #cccccc;
        border-bottom: 1px solid #cccccc;
        border-top: 1px solid #ffffff;
        z-index: 2;
        transform: rotate(45deg);
    }
    .rate-blank {
        position: relative;
        left: 0;
        top: 0;
        width: 50px;
        cursor: pointer;
        .text {
            border: 1px solid #cccccc;
            padding: 2px;
            border-radius: 1px;
            color: #999999;
            font-size: 10px;
        }
        .rate-val {
            background: #ffffff;
            position: absolute;
            right: 11px;
            top: 13px;
            height: 10px;
            line-height: 10px;
            font-size: 7px;
            padding-left: 2px;
            text-align: right;
        }
    }
    .load-btn {
        width: 42px;
        height: 42px;
        margin: 0 auto;
        cursor: pointer;
        background: red;
        border-radius: 21px;
        line-height: 42px;
    }
    .play-btn {
        width: 42px;
        height: 42px;
        margin: 0 auto;
        background-image: url('@/assets/ic_play.png');
        background-size: 100%;
        background-repeat: no-repeat;
        cursor: pointer;
    }
    .pause-btn {
        background-image: url('@/assets/ic_pause.png');
    }
}
.custom-button {
    width: 12px;
    height: 12px;
    background: #fd453d;
    box-shadow: 0 2px 4px 0 rgba(253, 69, 61, 0.67);
    border-radius: 50%;
}
</style>
